enum ReplayType {
    daikai = 1,
    circle
}
//回放播放器
class Replayer implements IUpdate {

    //被分享的字段
    static shareIF = {
        isSharePlayback: false,//分享回放状态
        pre: "pb_#",
        uid: null,
        item_id: null,
        playback_id: null,
        share_desc: null
    };

    //分享的回放数据请求
    static requestPlayback() {
        let IF = Replayer.shareIF;
        SocketManager.i.send(71, {
            item_id: IF.pre + IF.item_id,
            playback_id: IF.pre + IF.playback_id
        });
    }

    //接收回放的分享数据
    static responsePlayback(data: any) {
        gameManager.close('LoginScene');
        game.roomid = +data.roomid;
        game.recordInfos = data.persons;
        Replayer.i.parseData(data.playback);
    }

    static _i: Replayer;

    constructor() {
        this.clear();
        GSUpdate.i.addUpdate(this);
    }

    static get i() {
        return Replayer._i || (Replayer._i = new Replayer);
    }

    static replaySpeed: number = 800;
    static startDelay: number = 1000;

    actions: any;

    interval: number;

    passTime: number;

    data: any;

    //缓存牌
    cachePaiArr: any;


    //当前步骤
    lastIndex: number;

    //步骤
    index: number;

    //是否暂停
    //isPause:boolean;

    //是否回退
    isFB: boolean;

    exitInterval: number;

    funcInterval: number;

    //本地锁
    lock: boolean;
    //锁定计数
    lockCount: number;

    lockMaxCount: number = 10;

    action_10_lock: boolean;

    /**单局结算界面显示*/
    resultViewShow: boolean;
    // resultTimeId: number;
    beginTime: number;

    clear() {

        //this.isPause = false;
        this.isFB = false;

        this.index = 0;

        this.lastIndex = 0;

        this.passTime = 0;

        this.stop = true;

        this.actions = [];

        this.lock = false;

        this.action_10_lock = false;

        egret.clearTimeout(this.interval);

        egret.clearTimeout(this.exitInterval);

        //关闭控制菜单
        GSController.i.gsView.replayMenu.visible = false;

        GSController.i.gsView.replayMenu.play();

        this.clearFuncView();

    }

    exit() {
        console.log("-----回放结束!-----");

        EffectTextUtils.showTips("回放结束", 5);
        game.roomClean();
        GSController.i.exit();

        this.clear();

        game.askPanel.hide();

        switch (game.ReplayType) {
            case ReplayType.daikai:
                break;
            case ReplayType.circle:
                GSDataProxy.i.sendCircleOpen();
                break;
            default:
                gameManager.open('RecordPanel');
                break;
        }

    }

    /*
     回放
     */
    /*Replay(){
     this.clear();
     PublicVal.i.clear();
     this.parseData(this.data);
     }*/
    /*
     暂停
     */
    Pause() {

        //this.isPause = true;
        this.stop = true;
    }

    /*
     播放
     */
    Play() {

        this.stop = false;
    }

    /*
     快进
     */
    FF() {

        this.passTime = Replayer.replaySpeed;

        this.lockCount = this.lockMaxCount;
    }

    /*
     回退
     */
    FB() {
        this.beginTime = undefined;
        this.clearResultView();

        this.clearExitInterval();

        PublicVal.i.clear();

        this.clearFuncView();

        for (let i: number = 1; i <= 4; i++) {
            let mjview: GameSceneMJLayer = GSController.i.gsView.MJViews[i];
            mjview.huview.clean();
        }

        this.isFB = true;
        this.actions = [];
        this.parseData(this.data);

        this.lastIndex--;
        this.prevIndex(this.lastIndex);
        this.index = this.lastIndex + 1;
        if (this.lastIndex == -1) {
            this.lastIndex = 0;
        }
        this.isFB = false;
        this.passTime = 0;

    }

    /*
     退到某步
     */
    prevIndex(index: number) {

        if (index < 0) return;

        //console.log("--------回退开始");

        let i: number = 0;

        while (i <= index) {
            this.goIndex(i);
            i++;
        }

        //console.log("--------回退结束");
        this.passTime = 0;
    }

    /*
     [?Record_Action_Static,Static],
     [?Record_Action_Init,Shou1],
     [?Record_Action_Draw,Tp1,Nu1,Turn]，
     [?Record_Action_Play,Type,Number,Turn],
     [?Record_Action_Notice,Turn,Pos,Interrupts],
     [?Record_Action_Deal,POS,Action,RtnPai]

     -1).初始化手牌
     -2).%打牌
     -3).%抓牌
     -4).%通知功能菜单
     -5).%处理功能菜单点击
     -6).%当局静态数据
     -7).%换宝
     Static6 =
     [
     data([rules]),
     data([dui_num]),
     data([cur_round]),
     data([max_round])
     ]
     Shou1 =
     [
     get_shou_origin(1),
     get_shou_origin(2),
     get_shou_origin(3),
     get_shou_origin(4)
     ]
     */
    parseData(data: any) {

        if (data == null) return;

        this.data = data;

        this.parsePersons(game.recordInfos);

        PublicVal.i.roomOwnFlag = 1 << this.returnDir(1);

        for (let i: number = 0; i < data.length; i++) {
            let arr = data[i];
            let action: number = arr[0];
            this["__action_" + action](arr, i);
        }
        this.show();
    }

    __action_7(arr: any, index: number) {

        this.actions.push({ index: index, action: 7, pai: arr[1] });

    }


    __action_1(arr: any, index: number) {
        this.cachePaiArr = arr;

        let all = arr[1];
        let obj: any;
        let pais: any[];
        for (let i: number = 0; i < all.length; i++) {

            obj = all[i];
            pais = this.formatPai(1, obj[1]).concat(this.formatPai(2, obj[2])).concat(this.formatPai(3, obj[3])).concat(this.formatPai(4, obj[4])).concat(this.formatPai(5, obj[5]));

            // console.log(this.returnDir(i + 1));

            PublicVal.i.allPais[this.returnDir(i + 1)].handPais = pais;
        }
    }

    __action_2(arr: any, index: number) {
        this.actions.push({ action: 2, pai: { type: arr[1], number: arr[2] }, pos: arr[3] });
    }

    __action_3(arr: any, index: number) {
        this.actions.push({ action: 3, pai: { type: arr[1], number: arr[2] }, pos: arr[3] });
    }

    __action_4(arr: any, index: number) {

        //旧版本直接返回
        if (!PublicVal.i.replayVer || arr[3].length < 2 || (arr[3].length == 2 && arr[3].indexOf(9999) > -1)) return;

        this.actions.push({ action: 4, funcs: arr[3], pos: arr[2] });
    }

    //功能选择
    __action_8(arr: any, index: number) {
        if (arr[1] == 35 || arr[1] == 9999) {
            return;
        }
        this.actions.push({ action: 8, funcID: arr[1] });
    }

    //删除某人手牌
    __action_9(arr: any, index: number) {

        this.actions.push({ action: 9, from: arr[1], pos: arr[2], pai: arr[3] });
    }

    //解散房间
    __action_10(arr: any, index: number) {

        let agrees = []; //根据pos存储选择

        for (let i: number = 1; i < arr.length; i += 2) {

            agrees.push({ pos: arr[i], agree: arr[i + 1] });

        }
        this.actions.push({ action: 10, agree: agrees });

    }

    __action_11(arr: any, index: number) {
        GSData.i.result = arr[1];
        this.actions.push({ action: 11 });
    }

    __action_5(arr: any, index: number) {

        let pos: number = arr[1];

        let funcID: number = arr[2];

        switch (funcID) {
            case 0://过
                if (!PublicVal.i.replayVer) return;
                this.actions.push({ index: index, action: 5, funcID: funcID, pos: pos });
                break;
            case 1://吃
            case 2://碰
            case 22://幺九杠
            case 23://旋风杠
            case 24://暗杠
            case 26://中发白杠
            case 27://幺九杠的补蛋
            case 28://中发白杠的补蛋
                this.actions.push({
                    index: index,
                    action: 5,
                    funcID: funcID,
                    pais: arr[3],
                    pos: pos,
                    from: arr[3][1].pos
                });
                break;
            case 25://明杠
                this.actions.push({
                    index: index,
                    action: 5,
                    funcID: funcID,
                    pais: arr[3],
                    pos: pos,
                    from: arr[3][0].pos
                });
                break;
            case 4://听牌
            case 1001://潇洒
                this.actions.push({ index: index, action: 5, funcID: funcID, pos: pos });
                break;
            case 99://胡牌
                this.actions.push({ index: index, action: 5, funcID: funcID, pai: arr[3], pos: pos, from: arr[3].pos });
                break;
        }
    }

    __action_6(arr, index: number) {
        const info = arr[1];
        game.roomRules = info[0];
        game.roomPaidui = info[1];
        game.roomRoundCur = info[2];
        game.roomRound = info[3];
        game.roomRoundType = info[7];
        if (info[8]) {
            game.roomid = info[8];
        }
        PublicVal.i.bao = info[4];
        PublicVal.i.zhuang = info[5];
        PublicVal.i.replayVer = info[6];

        PublicVal.i.zhuangFlag = 1 << this.returnDir(PublicVal.i.zhuang);
        //console.log(PublicVal.i.rules,game.roomPaidui,PublicVal.i.cur_round,PublicVal.i.max_round);
    }

    //展示
    show() {

        game.roomReady();

        PublicVal.state = StateType.replay;
        GSController.i.startView();
        GSConfig.replayConfigInit();

        GSController.i.gsView.replayMenu.visible = true;

        GSController.i.nullAllHead();
        GSController.i.setArrowDir(0);
        GSController.i.setBoomDir(PublicVal.i.ownPos);
        GSController.i.visibleRoomOwn();
        GSController.i.visibleZhuang();
        GSController.i.updateBaoView();
        GSController.i.updateReplayRoom(PublicVal.i.dirPerson);
        GSController.i.gsView.updateState();
        if (Replayer.shareIF.isSharePlayback) GSController.i.visibleFourFuncButton(false, false);
        this.__play();

        gameManager.i.dispatchEvent(GameEventType.UPDATE_ROOM_INFO);
    }

    __play() {

        this.initMJViews();

        if (!this.isFB) {

            this.interval = egret.setTimeout(_ => {
                this.Play();
                this.passTime = 0;
            },
                this, 1000);
        }
    }

    /*
     初始化麻将
     */
    initMJViews() {
        let dir;
        for (let i: number = 1; i <= game.roomSeat; i++) {
            dir = this.returnDir(i);
            // console.log("**************************");
            // console.log(PublicVal.i.getHandPais(dir));
            FashionTools.sortPai(PublicVal.i.getHandPais(dir));
            GSController.i.updateMJView(dir);
            GSController.i.updatePoolPaiView(dir);
        }

        let headView;
        for (let i: number = 1; i <= 4; i++) {
            headView = GSController.i.gsView.headViews[i];
            headView.visible = PublicVal.i.getPos(i)
        }
    }


    //解析玩家
    parsePersons(list: any) {

        PublicVal.i.posPerson = [];

        if (Replayer.shareIF.isSharePlayback) game.player.uid = Replayer.shareIF.uid;

        for (let i: number = 0; i < list.length; i++) {

            let person = list[i];

            PublicVal.i.posPerson[person.pos] = person;

            if (game.player.uid == person.uid) {
                PublicVal.i.ownPos = person.pos;
            }

            if (game.ReplayType) {
                PublicVal.i.ownPos = 1;
            }
        }

        game.roomSeat = list.length;

        GameHandy.mappingDir(1);

        PublicVal.i.pos2Dir = {};
        PublicVal.i.dirPerson = [];

        //确定方位
        let a = PublicVal.i.ownPos;

        let b, c, d;

        PublicVal.i.pos2Dir[a] = 1;

        PublicVal.i.dirPerson[1] = PublicVal.i.posPerson[a];

        switch (game.roomSeat) {

            case 2:
                b = 1 + a % game.roomSeat;
                PublicVal.i.pos2Dir[b] = 3;
                PublicVal.i.dirPerson[3] = PublicVal.i.posPerson[b];
                break;
            case 3:
                b = 1 + a % game.roomSeat;
                c = 1 + (a + 1) % game.roomSeat;

                PublicVal.i.pos2Dir[b] = 2;
                PublicVal.i.pos2Dir[c] = 4;

                PublicVal.i.dirPerson[2] = PublicVal.i.posPerson[b];
                PublicVal.i.dirPerson[4] = PublicVal.i.posPerson[c];

                break;
            case 4:

                b = 1 + a % game.roomSeat;
                c = 1 + (a + 1) % game.roomSeat;
                d = 1 + (a + 2) % game.roomSeat;
                PublicVal.i.pos2Dir[b] = 2;
                PublicVal.i.pos2Dir[c] = 3;
                PublicVal.i.pos2Dir[d] = 4;
                PublicVal.i.dirPerson[2] = PublicVal.i.posPerson[b];
                PublicVal.i.dirPerson[3] = PublicVal.i.posPerson[c];
                PublicVal.i.dirPerson[4] = PublicVal.i.posPerson[d];
                break;

        }
    }

    //返回dir
    returnDir(pos: number) {
        return PublicVal.i.pos2Dir[pos];
    }

    play_action_2(action: any) {

        let pos = action.pos;
        let pai = action.pai;
        let dir = this.returnDir(pos);


        // console.log("打牌", action, pai);

        PublicVal.i.removeHandPai(dir, pai);

        PublicVal.i.pushPoolPai(dir, pai);


        GSController.i.updateMJView(dir);

        GSController.i.updatePoolPaiView(dir);

    }

    play_action_3(action: any) {

        let pos = action.pos;
        let pai = action.pai;
        let dir = this.returnDir(pos);

        // console.log("抓牌", action, pai);

        PublicVal.i.addHandPai(dir, pai, false);

        GSController.i.updateMJView(dir);

        game.roomPaidui--;

        GSController.i.updateCenterInfo();

    }

    //换宝
    play_action_7(action: any) {

        PublicVal.i.bao = action.pai;

        game.roomPaidui--;

        GSController.i.updateBaoView();

        GSController.i.updateCenterInfo();

        if (!this.isFB) {

            GSController.i.gsView.changeBao();
        }
    }

    //展示功能菜单
    play_action_4(action: any) {

        //this.stop = true;

        let pos = action.pos;

        let funcs = action.funcs;

        let dir = this.returnDir(pos);

        GSController.i.gsView.frontUIContainer.addReplayFuncs(dir, action.funcs);

    }

    play_action_8(action: any) {

        let funcID = action.funcID;

        this.lock = true;

        this.lockCount = 0;

        GSController.i.gsView.frontUIContainer.handFocus(funcID);

        if (this.isFB) {

            //child.call(this,action);
            this.clearFuncView();
        } else {
            this.funcInterval = egret.setInterval(_ => {

                this.lockCount++;

                if (this.lockCount >= this.lockMaxCount) {
                    //child.call(this, action);
                    this.clearFuncView();
                }
            }, this, 100);
        }
    }

    play_action_9(action: any) {

        let dir = this.returnDir(action.from);

        PublicVal.i.removeHandPai(dir, action.pai);

        GSController.i.updateMJView(dir);

    }

    play_action_10(action: any) {

        if (this.isFB) return;

        let dialog: DissolutionPanel = gameManager.find('DissolutionPanel');

        if (dialog) {

            this.action_10_lock = true;

            dialog.show();
            //dialog.refresh();
            dialog.replayRefresh(PublicVal.i.posPerson);

            let index = 0;

            dialog.replayAgree(action.agree[index]);

            let interval = egret.setInterval(
                _ => {
                    index++;
                    if (index == action.agree.length) {
                        egret.clearInterval(interval);
                        dialog.hide();
                        this.action_10_lock = false;
                        return;
                    }
                    dialog.replayAgree(action.agree[index]);
                }, this, 800);
        }
    }
    /**回放界面显示 */
    play_action_11(action: any) {
        GSController.i.closeGSView();
        GSDataProxy.i.delay_Final();
        GSController.i.showReplayMenu();
        this.resultViewShow = true;
        this.beginTime = game.getTimesamp();
        /**this.resultTimeId = egret.setTimeout(() => {
            this.resultViewShow = false;
            GSController.i.hideReplayMenu();
        }, this, 50000);*/
    }

    play_action_5(action: any) {

        child.call(this, action);

        function child(action: any) {
            let funcID = action.funcID;
            let pos = action.pos;
            let from = action.from;
            let pais = action.pais;
            let pai = action.pai;

            let dir = this.returnDir(pos);
            let fromDir = this.returnDir(from);

            let sPais;
            let everPai;
            let everSrc;

            switch (funcID) {
                case 1:
                    PublicVal.i.removeHandPai(dir, pais[0], false);
                    PublicVal.i.removeHandPai(dir, pais[2]);
                    PublicVal.i.popPoolPai(fromDir);
                    PublicVal.i.addFuncPai(5, dir, funcID, pais);
                    GSController.i.updateMJView(dir);
                    GSController.i.updatePoolPaiView(fromDir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 2:
                    PublicVal.i.removeHandPai(dir, pais[0], false);
                    PublicVal.i.removeHandPai(dir, pais[2]);
                    PublicVal.i.popPoolPai(fromDir);
                    PublicVal.i.addFuncPai(4, dir, funcID, pais);
                    GSController.i.updateMJView(dir);
                    GSController.i.updatePoolPaiView(fromDir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 4://听
                    var head: HeadIcon = GSController.i.gsView.getHeadView(dir);
                    head.isTing = true;
                    this.playFuncEffect(dir, funcID);
                    break;
                case 24://暗杠
                    PublicVal.i.removeHandPai(dir, pais[0], false);
                    PublicVal.i.removeHandPai(dir, pais[1], false);
                    PublicVal.i.removeHandPai(dir, pais[2], false);
                    PublicVal.i.removeHandPai(dir, pais[3]);
                    PublicVal.i.addFuncPai(1, dir, funcID, pais);
                    GSController.i.updateMJView(dir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 25://明杠
                    let pai0 = pais[0];
                    let hasPeng: boolean = PublicVal.i.removePengFunc(dir, pai0);
                    if (hasPeng) {//有碰的明杠
                        PublicVal.i.removeHandPai(dir, pai0);
                    } else {
                        PublicVal.i.popPoolPai(fromDir);
                        PublicVal.i.removeHandPai(dir, pai0, false);
                        PublicVal.i.removeHandPai(dir, pai0, false);
                        PublicVal.i.removeHandPai(dir, pai0);
                    }
                    PublicVal.i.addFuncPai(2, dir, funcID, pais);

                    GSController.i.updateMJView(dir);
                    GSController.i.updatePoolPaiView(fromDir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 22:
                    PublicVal.i.removeHandPai(dir, pais[0], false);
                    PublicVal.i.removeHandPai(dir, pais[1], false);
                    PublicVal.i.removeHandPai(dir, pais[2]);

                    PublicVal.i.addFuncPai(3, dir, funcID, pais, pais[0].number, true);

                    GSController.i.updateMJView(dir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 23:
                    PublicVal.i.removeHandPai(dir, pais[0], false);
                    PublicVal.i.removeHandPai(dir, pais[1], false);
                    PublicVal.i.removeHandPai(dir, pais[2], false);
                    PublicVal.i.removeHandPai(dir, pais[3]);

                    PublicVal.i.addFuncPai(4, dir, funcID, pais);

                    // PublicVal.i.addFuncPai(4, dir, funcID, pais, pais[0].number, true);
                    GSController.i.updateMJView(dir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 26://中发白杠
                    PublicVal.i.removeHandPai(dir, pais[0], false);
                    PublicVal.i.removeHandPai(dir, pais[1], false);
                    PublicVal.i.removeHandPai(dir, pais[2]);

                    PublicVal.i.addFuncPai(0, dir, funcID, pais, 0, true);

                    GSController.i.updateMJView(dir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 27://幺九杠 补蛋
                    //pais.length -= 3;
                    sPais = pais.slice(0, -3);

                    everPai = PublicVal.i.getPai(dir, 22, sPais[0].number);

                    everSrc = [1, 1, 1];

                    for (let i: number = 0; i < sPais.length; i++) {
                        everSrc[sPais[i].type - 1]++;
                    }
                    everPai.ever = everSrc;
                    PublicVal.i.removeHandPai(dir, sPais[0]);
                    GSController.i.updateMJView(dir);
                    this.playFuncEffect(dir, funcID);

                    break;
                case 28://中发白 补蛋
                    //pais.length -= 3;
                    sPais = pais.slice(0, -3);

                    everPai = PublicVal.i.getPai(dir, 26);

                    everSrc = [1, 1, 1];

                    for (let i: number = 0; i < sPais.length; i++) {
                        everSrc[sPais[i].number - 1]++;
                    }
                    everPai.ever = everSrc;
                    PublicVal.i.removeHandPai(dir, sPais[0]);
                    GSController.i.updateMJView(dir);
                    this.playFuncEffect(dir, funcID);
                    break;
                case 99:
                    if (from && pos != from) {//点炮
                        console.log("点炮!");

                        if (GameConfig.gameType != GameType.sichuan) PublicVal.i.addHandPai(dir, pai, false);

                        PublicVal.i.popPoolPai(fromDir);

                        GSController.i.updateMJView(dir);
                        GSController.i.updatePoolPaiView(fromDir);
                    } else {
                        console.log("自摸胡牌!");
                        if (GameConfig.gameType == GameType.sichuan) PublicVal.i.removeHandPai(dir, pai);
                        GSController.i.updateMJView(dir);
                    }

                    if (GameConfig.gameType == GameType.sichuan) {
                        let mjview: GameSceneMJLayer = GSController.i.gsView.MJViews[dir];
                        mjview.pushHu(pai);
                    }

                    this.playFuncEffect(dir, funcID);
                    break;
            }
        }
    }

    playFuncEffect(dir: number, funcID: number) {

        if (!this.isFB) {
            GSController.i.playEffect(dir, funcID);
        }

    }

    update(advanceTime: number, timeStamp?: number): void {

        if (this.lock || this.action_10_lock) return;

        this.passTime += advanceTime;

        if (this.resultViewShow) {
            this.checkDoCallBack(5000, this.clearResultView, this, !Replayer.shareIF.isSharePlayback);
            return;
        }

        if (this.passTime >= Replayer.replaySpeed) {

            if (this.index < this.actions.length) {

                this.goIndex(this.index);

                this.passTime = 0;

                this.index++;

            } else {
                this._replayerOver();
            }
        }
    }

    private _replayerOver(time: number = 3000) {


        this.stop = true;
        //同步下控制按钮
        GSController.i.gsView.replayMenu.pause();
        GameSceneReplayMenu.pause();
        this.clearExitInterval();

        if (!Replayer.shareIF.isSharePlayback) {
            this.exitInterval = egret.setTimeout(this.exit, this, time);
        }
    }

    clearExitInterval() {
        if (this.exitInterval) {
            egret.clearTimeout(this.exitInterval);
        }
    }


    goIndex(index: number) {

        let action = this.actions[index];

        this["play_action_" + action.action](action);

        this.lastIndex = index;

    }

    clearFuncView() {

        this.lock = false;

        egret.clearInterval(this.funcInterval);

        GSController.i.gsView.frontUIContainer.clear();
    }

    clearResultView(flag: boolean = true) {
        this.resultViewShow = false;
        if (GSController.i.gsResultView.visible == true) {
            if (flag) {
                GSController.i.closeResultView();
            }
            this._replayerOver(0);
        }
    }
    /**根据启动时间检测是否执行 */
    checkDoCallBack(diff: number, func: Function, thisObj: any, ...params: any[]) {
        if (this.beginTime != undefined) {
            const time = game.getTimesamp();
            if (time - this.beginTime >= diff) {
                func.apply(thisObj, params);
            }
        }
    }

    completed: boolean;
    //自动移除
    autoRemove: boolean;
    //停止刷新
    stop: boolean;

    //格式化牌型
    private formatPai(type: number, nums: number[]) {
        if (nums) {
            let arr = [];
            for (let i: number = 0; i < nums.length; i++) {
                arr.push({ type: type, number: nums[i] });
            }
            return arr;
        }
        return [];
    }
}